package edu.washington.ling.syntric.io;

import java.util.LinkedList;

import edu.washington.ling.syntric.struct.error.UnreadableRepresentationException;
import edu.washington.ling.syntric.struct.tree.Node;
import edu.washington.ling.syntric.struct.tree.Token;
import edu.washington.ling.syntric.struct.tree.Tree;

public class TreeReaderPTB extends TreeReader {

	private Node parseTree(String elem, final LinkedList<String> treeElems, final Tree ps) {
		if (!elem.equals("(")) return null;
		
		final Node node = new Node();
		
		if (!treeElems.peek().equals("(")) {
			String label = treeElems.pop();
			node.setLabel(label);
		} else {
			node.setLabel("");
		}
		
		while (treeElems.size() > 0) {
			elem = treeElems.pop();
			
			if (elem.equals(")")) return node;
			
			else if (elem.equals("(")) {
				Node child = parseTree(elem, treeElems, ps);
				child.setPSParent(node);
				node.addPSChild(child);
			}
			else {
				Token word = new Token();
				
				word.setWord(elem);
				word.setPSParent(node);
				node.addPSChild(word);
				ps.addToken(word);
			}
		}
		return node;
	}

	private LinkedList<String> getTreeElems(String[] treeLines) {
		LinkedList<String> treeElems = new LinkedList<String>();
		for (String treeLine: treeLines) {
			String[] lineElems = treeLine.split("(?=[()])|(?<=[()])|\\s+");
			for (String lineElem: lineElems) {
				lineElem = lineElem.trim();
				if (lineElem.length() > 0) { treeElems.add(lineElem); }
			}
		}
		return treeElems;
	}
	
	@Override
	public Tree readTree(TreeRepresentation tr) {
		Tree tree = new Tree(tr.getLayer());
		tree.setMetaData(tr.getMetaData());
		String[] lines = tr.getTreeLines();
		LinkedList<String> treeElems = getTreeElems(lines);
		if (treeElems.size() > 0) {
			Node root = parseTree(treeElems.pop(), treeElems, tree);
			tree.setPSRoot(root);
		}
		return tree;
	}

	@Override
	public void checkRepFormat(TreeRepresentation rep)
			throws UnreadableRepresentationException {
	}
	@Override
	public String getFormat() {
		return "ptb";
	}
}
